package com.api.shopapi.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.*;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.api.shopapi.config.AlipayConfig;
import com.api.shopapi.config.BarcodePayConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;


import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Slf4j
public class AliPayUtils {




    /**
     * 支付宝订单支付
     * @param orderNumber 订单编号
     * @param totalAmount 订单金额（元）
     * @return
     * @throws Exception
     */
    public static String aliPay(String orderNumber, String totalAmount,String subject,String body,String notifyUrl) throws Exception {

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("orderNumber", orderNumber);
        jsonObject.put("totalAmount", totalAmount);
        String orderString = null;


        //实例化客户端
        AlipayClient alipayClient = AlipayConfig.initClient();
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setPassbackParams(JSON.toJSONString(jsonObject));//传递订单号和订单金额
        model.setBody(body); //对一笔交易的具体描述信息。如果是多种商品，请将商品描述字符串累加传给body。
        model.setSubject(subject); //商品标题
        model.setOutTradeNo(orderNumber); //商家订单编号
        model.setTimeoutExpress("30m"); //超时关闭该订单时间
        model.setTotalAmount(totalAmount);  //订单总金额
        model.setProductCode("QUICK_MSECURITY_PAY"); //销售产品码，商家和支付宝签约的产品码，为固定值QUICK_MSECURITY_PAY
        request.setBizModel(model);
        log.info("aliPayNotifyUrl:"+notifyUrl);
        request.setNotifyUrl(notifyUrl);  //回调地址
        try {
            //这里和普通的接口调用不同，使用的是sdkExecute
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            //就是orderString 可以直接给APP请求，无需再做处理。
            orderString = response.getBody();

            if (!response.isSuccess()) {
                return "支付失败:"+response.getSubMsg();
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        System.out.println("-------------"+orderString);
        return orderString;
    }



    /**
     * 支付宝条码支付
     * @param orderNumber 订单编号
     * @param totalAmount 订单金额（元）
     * @param subject 订单标题
     * @param authCode 用户付款码
     * @return
     * @throws Exception
     */
    public static String barcodePay(String orderNumber, String totalAmount,String subject,String authCode) throws Exception {

        //实例化客户端
        AlipayClient alipayClient = BarcodePayConfig.initClient();
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradePayRequest request = new AlipayTradePayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradePayModel model=new AlipayTradePayModel();
        model.setOutTradeNo(orderNumber);//订单号
        model.setScene("bar_code");
        model.setAuthCode(authCode);
        model.setSubject(subject);
        model.setTotalAmount(totalAmount);
        request.setBizModel(model);
        AlipayTradePayResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            return response.getBody();
        } else {
            return "支付失败:"+response.getSubMsg();
        }
    }

    public static AlipayTradePayResponse barcodePay2(String orderNumber, String totalAmount,String subject,String authCode) throws Exception {

        //实例化客户端
        AlipayClient alipayClient = BarcodePayConfig.initClient();
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradePayRequest request = new AlipayTradePayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradePayModel model=new AlipayTradePayModel();
        model.setOutTradeNo(orderNumber);//订单号
        model.setScene("bar_code");
        model.setAuthCode(authCode);
        model.setSubject(subject);
        model.setTotalAmount(totalAmount);
        request.setBizModel(model);
        AlipayTradePayResponse response = alipayClient.execute(request);
        return response;
    }


    /**
     * 支付宝条码支付退款
     * @param orderNumber 订单编号
     * @param refundAmount 退款金额（元）
     * @return
     * @throws Exception
     */
    public static String barcodeRefund(String orderNumber, String refundAmount) throws Exception {

        //实例化客户端
        AlipayClient alipayClient = BarcodePayConfig.initClient();
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeRefundModel model=new AlipayTradeRefundModel();
        model.setOutTradeNo(orderNumber);//订单号
        model.setRefundAmount(refundAmount);
        request.setBizModel(model);
        AlipayTradeRefundResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            return response.getBody();
        } else {
            return "退款失败:"+response.getSubMsg();
        }
    }




    /**
     * 统一收单线下交易查询
     * @param orderNumber 订单号
     * @return
     */
    public static Map<String, String> aliPayOrderQuery(String orderNumber) {
        Map map = new HashMap();
        try {
            AlipayClient alipayClient = AlipayConfig.initClient();
            //创建API对应的request类
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            AlipayTradeQueryModel model = new AlipayTradeQueryModel();
            model.setOutTradeNo(orderNumber);
            request.setBizModel(model);
            //通过alipayClient调用API，获得对应的response类
            AlipayTradeQueryResponse response = alipayClient.execute(request);
            if (response.isSuccess()){
                map.put("tradeStatus",response.getTradeStatus());
            }else {
                map.put("查询订单失败",response.getSubMsg());
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return map;
    }



    /**
     * 支付宝退款：统一收单交易退款接口
     * 官方文档：https://opendocs.alipay.com/apis/api_1/alipay.trade.refund
     *
     * @param orderNumber 商户订单号
     * @param refundAmount 需要退款的金额，该金额不能大于订单金额,单位为元，支持两位小数
     * @author duanpj
     * @date 2020/4/27 1:22
     */
    public static Map<String, String> aliRefund(String orderNumber, Double refundAmount,String out_request_no) throws AlipayApiException {
        Map map = new HashMap();
        AlipayClient alipayClient = AlipayConfig.initClient();
        //创建API对应的request类
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
        model.setOutTradeNo(orderNumber);
        model.setOutRequestNo(out_request_no);//标识一次退款请求
        model.setRefundAmount(refundAmount.toString());
        model.setRefundReason("退款申请");
        request.setBizModel(model);
        //通过alipayClient调用API，获得对应的response类
        AlipayTradeRefundResponse response = alipayClient.execute(request);
        if (response.isSuccess()) {
            /** 退款金额 */
            map.put("refund_fee", response.getRefundFee());
            /** 商户订单号 */
            map.put("out_trade_no", response.getOutTradeNo());
            /** 退款支付时间 */
            map.put("gmt_refund_pay", response.getGmtRefundPay());
            map.put("out_request_no",out_request_no);
            map.put("refundType", "success");
            map.put("msg", "支付宝退款成功");
        }else {
            map.put("refundType", "fail");
            map.put("msg", "支付宝退款失败:" + response.getSubMsg());
        }
        return map;
    }


    /**
     * 统一收单线下退款交易查询
     * @param orderNumber 订单号
     * @return
     */
    public static Map<String, String> aliPayRefundOrderQuery(String orderNumber,String outRequestNo) {
        Map map = new HashMap();
        try {
            AlipayClient alipayClient = AlipayConfig.initClient();
            AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
            AlipayTradeFastpayRefundQueryModel model=new AlipayTradeFastpayRefundQueryModel();
            model.setOutTradeNo(orderNumber);
            model.setOutRequestNo(outRequestNo);
            request.setBizModel(model);
            AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
            if(response.isSuccess()){
                if (response.getRefundStatus().equals("")||response.getRefundStatus().equals("REFUND_SUCCESS")){
                    map.put("result","退款成功");
                }else {
                    map.put("result","退款失败");
                }
            } else {
                map.put("errorMsg", "支付宝退款查询失败:" + response.getSubMsg());
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return map;
    }


}
